#-*- coding: utf-8 -*-
"""My variant of the nicely thought but badly coded wCreateMrProxy script.

A tool to create mentalray binary proxies.

Can be both used as a script or with UI.
"""


import os
import pymel.core as pm






########################################################################
class MrProxy(object):
    """A mentalray proxy creator.
    
    Creates and handles mentalray proxy related data.
    
    Stores it self in an empty time node (which is a lightweight data storage)
    by pickling itself. The data node is called MrProxyData#.
    
    The stored data contains:
      
      * The original objects involved in the proxy
      * The combined objects (in case there are multiple source objects)
      * The proxy object
      * The path of the resulting .mi file
    
    If an MrProxy instance is created with multiple source objects, the objects
    are duplicated and then combined to create a proxy.
    
    The data object helps to recreate the mentalray proxy file when the source
    objects are changed. The data object holds the list of the source objects
    in the same order as they are given.
    
    The type of the place holder geometry can be defined by using the type
    argument or property. The types of the place holders are:
      
      0: proxy box
      1: proxy sphere
      2: proxy cylinder
      3: low poly proxy version of the original mesh
      4: another spesific object
    
    The proxy object will have enough polygon to be able to hold all the
    shaders of the original objects.
    
    The proxy objects will be fit in to the bounding box of the original
    objects. The bounding box information will be allways calculated from the
    source objects.
    
    :param hires_objects: The hires objects that want to be created a proxy
      for.
    
    :type hires_objects: list of pymel.core.nodeTypes.Transform
    
    :param int type: The type of place holder object.
    
    A usage example is as follows::
      
      import pymel.core as pm
      from oyMrBinaryProxyTools import MrProxy
      
      # create a binary proxy from the selected objects
      proxy = MrProxy(hires_objects=pm.ls(sl=1))
      
      # set the type to a spesific object
      proxy.type = 5
      
      # create a place holder
      place_holder = proxy.create_place_holder()
      
      # create the mi proxy file
      proxy.create_mibp_file()
      
      # save the proxy to the scene
      proxy.save()
      
      # load a proxy from the scene
      new_proxy = MrProxy()
      
      # get a list of MrProxyData nodes in the scene
      
      dataNodes = new_proxy.list_saved_nodes()
      
      # load the node from the first node if there is any
      if len(dataNodes):
          new_proxy.load_from_data_node(dataNodes[0])
      
      # update the object list and update the mi file
      box = pm.modeling.polyCube()[0]
      
      new_proxy.hires_objects.append(box)
      new_proxy.create_mibp_file()
      new_proxy.save()
    
    """
    
    
    
    #----------------------------------------------------------------------
    def __init__(self, hires_objects=[], type=0):
        
        self._hires_objects = []
        self._type = 0
        self._place_holder = None
        self._min_poly_count = 1
    
    
    
    #----------------------------------------------------------------------
    def create_place_holder(self):
        """Creates the lowres proxy place holder.
        
        Creates the lowres place holder.
        
        :param obj: An instance of :class:`pymel.nodeTypes.Transform` holding
          the geometry that wanted to be created a Place Holder.
          
        :param string type: The type of the placeholder, can be selected from
          the list below:
            
            * 0: Box
            * 1: Sphere
            * 2: Cylinder
            * 3: Cross Planes
            * 4: Low Mesh Reduce
            * 5: Specify object (not created by this function)
        
        :param min_poly_count: Defines the minumum polygon count needed.
        """
    
        # get the bounding box of the object
        assert(isinstance(obj, pm.nodeType.nodetypes.Transform))
    
        bbox = obj.getBoundingBox()
    
        # call the appropriate function according to given type
        if type==0:
            return create_box(bbox, min_poly_count)
        elif type==1:
            return create_sphere(bbox)
        elif type==2:
            return create_cylinder(bbox)
        elif type==3:
            return create_cross_planes(bbox)
        elif type==4:
            return create_low_res_mesh(obj)
    
    
    
    #----------------------------------------------------------------------
    def _create_proxy_box(self):
        """Creates a proxy box fitting the given bbox..
    
        :param bbox: The desired bounding box of the box.
    
        :param min_poly_count: The mininum number of polygon needed.
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def _create_proxy_sphere(self):
        """Creates a proxy sphere fitting the given bbox.
    
        :param bbox: The desired bounding box of the box.
    
        :param min_poly_count: The mininum number of polygon needed.
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def _create_proxy_cylinder(self):
        """Creates a proxy cylinder fitting the given bbox.
        
        :param bbox: The desired bounding box of the box.
        
        :param min_poly_count: The mininum number of polygon needed.
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def _create_proxy_cross_planes(self):
        """Creates a proxy cross plane object fitting the given bbox.
        
        :param bbox: The desired bounding box of the box.
        
        :param min_poly_count: The mininum number of polygon needed.
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def create_proxy_low_res_mesh(self):
        """Creates a proxy loweres out of given polygon object
        
        :param obj: The object that needs to be reduced. Should be an instance
          of :class:`pymel.noteTypes.Transform` instance.
          
        :param min_poly_count: The mininum number of polygon needed.
        """
    
        pass
    
    
    
    #----------------------------------------------------------------------
    def _validate_file_path(self, file_path_in):
        """Validates the given file path.
        
        No hard validation for now. But may be in future it will be expanded.
        """
        
        # file_path_in should be an instance of string or unicode
        if not isinstance(file_path_in, (str, unicode)):
            raise ValueError("file_path should be an instance of string or"
                             "unicode")
        
        return file_path_in
    
    
    
    #----------------------------------------------------------------------
    def _get_shaders(self, obj):
        """Returns the assigned shaders of the given object.
        
        Returns the assigned shaders of the given object as a list.
        
        :param obj: The object in query. Should be an instance of
          `pymel.core.nodeTypes.Transform` instance.
        
        :type obj: `pymel.core.nodeTypes.Transform`
        
        :returns: list of `pymel.core.nodetypes.ShadingEngine`
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def _get_shader_count(self, obj):
        """Returns the assigned shader count of the given object.
        
        Returns the assigned shaders count of the given object.
        
        :param obj: a `pymel.nodeTypes.Transform` instance
        
        :type obj: `pymel.nodeTypes.Transform`
        
        :returns int: the number of assigned shaders of this object
        """
        
        pass
    
    
    
    #----------------------------------------------------------------------
    def _create_binary_proxy(self, obj, place_holder, file_path):
        """Creates an mr binary proxy for the given object.
    
        Creates the mr binary proxy for the given object and assigns it to the
        given place_holder object.
        
        :param obj: A :class:`pymel.nodeTypes.Transfrom` instance holding the
          object which wanted to be converted to an mr binary proxy.
        
        :param place_holder: A :class:`pymel.nodeTypes.Transform` instace
          holding the place_holder.
        
        :param file_path: The file path for the resulting .mi file.
        
        :returns: The mentalray binary proxy node.
        """
        
        # check if the obj is a Transform node
        if not isinstance(obj, pm.nodetypes.Transform):
            raise ValueError("obj must be an instance of "
                             "pymel.core.nodeTypes.Transform instance")
        
        # check if the place_holder is a Transform node
        if not isinstance(place_holder, pm.nodetypes.Transform):
            raise ValueError("place_holder must be an instance of "
                             "pymel.core.nodeTypes.Transform instance")
        
        # check if the file_path is a vali file path
        file_path = validate_file_path(file_path)
        
        # now create a mentalray binary proxy
        
        # check if mayatomr is loaded and load it if it is not
        pm.loadPlugin("Mayatomr")
        
        # check if the place_holder has a mesh shape
        obj_shape = obj.getShape()
        #if not isinstance(
        